//note:  this won't compile - these are just template procedures
const var EXTENDED_DEPTH : int = 3;
const Var MAX_PLAYER = true;

proc newAlphaBeta(gameBoard, ply : int, alpha : int, beta : int, Player : bool){
  
   if (isTerminalState(state) != "*"){
        //TODO: somehow edit the master class?  What do we actually want to happen here?
        return (gameBoard.evalState(state));
   }
   if (ply == 0){
         //minDepth reached, now go deeper in parallel
        return parallelAlphaBetaCrazySpectacular(gameBoard, EXTENDED_DEPTH, Player);
   }
   if (Player == MAX_PLAYER){
         //instance vars not necessary, but makes method calls cleaner
         currAlpha = this.MasterChief.getAlpha();
         currBeta = this.MasterChief.getBeta();
         for child in gameBoard.getChildren(){
             newVal= this.newAlphaBeta(child, currAlpha, currBeta, ply - 1);
             this.MasterChief.setAlpha(max(currAlpha, newVal));
             if (currBeta <= this.MasterChief.getAlpha())
                        break;
         //returning alpha value unnecessary because of master class
  } else {
         //instance vars not necessary, but makes method calls cleaner
         currAlpha = this.MasterChief.getAlpha();
         currBeta = this.MasterChief.getBeta();
         for child in gameBoard.getChildren(){
             newVal= this.newAlphaBeta(child, currAlpha, currBeta, ply - 1);
             this.MasterChief.setBeta(min(currBeta, newVal));
             if (this.MasterChief.getBeta() <= currAlpha)
                        break;
         //returning beta value unnecessary because of master class
  }
}

proc parallelAlphaBetaCrazySpectacular(gameBoard, depth : int, Player : bool){
  coforall child in gameBoard.getChildren() do {
      //perform regular serial alpha beta on each of these children to Extended_Depth
      alphaBeta(child, depth, this.MasterChief.getAlpha(), this.MasterChief.getBeta(), !Player);
  }
}


//regular alpha-beta pruning
//does not have waiting conditions
proc alphaBeta(gameBoard, ply : int, alpha : int, beta : int, Player : bool){
  
   if (isTerminalState(state) != "*" || ply == 0){
        return (gameBoard.evalState(state));
   }

   if (Player == MAX_PLAYER){
         for child in gameBoard.getChildren(){
             newVal= this.newAlphaBeta(child, alpha, beta, ply - 1);
             alpha = max(alpha, newVal);
             if (beta <= alpha){
                   break;
             }
         return alpha;
  } else {
         for child in gameBoard.getChildren(){
             newVal= this.newAlphaBeta(child, alpha, beta, ply - 1);
             beta = min(beta, newVal);
             if (beta <= alpha){
                   break;
             }
         return beta;
  }
}
